# 设置最低 CMake 版本要求
cmake_minimum_required(VERSION 3.16)

set(CMAKE_MSVC_EXTERNAL_INCLUDE_DIRECTORIES "")

# 定义项目名称、版本和语言
project(p2pms_client_sdk VERSION 1.0.0 LANGUAGES CXX)

# 设置 C++ 标准为 C++17，并禁用编译器扩展
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# 确保支持多配置生成器
if(CMAKE_GENERATOR MATCHES "Visual Studio")
    set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "Available configuration types" FORCE)
endif()

# 如果未指定构建类型，默认为 Debug
if(NOT CMAKE_BUILD_TYPE)
	set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build." FORCE)
endif()

# 设置输出目录
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)

# --- libwebrtc  ---

# 路径需要在调用 CMake 时通过命令行参数传入
set(LIBWEBRTC_INCLUDE_PATH 
	""
	CACHE
	PATH 
	"Path to libwebrtc include directory")
set(LIBWEBRTC_BINARY_PATH 
	""
	CACHE
	FILEPATH 
	"Path to libwebrtc library file")
set(ABSL_INCLUDE_PATH 
	""
	CACHE
	PATH 
	"Path to absl include directory")

# 检查路径是否已设置，如果未设置则配置失败
if(NOT LIBWEBRTC_INCLUDE_PATH)
    message(FATAL_ERROR "LIBWEBRTC_INCLUDE_PATH is not set.")
endif()
if(NOT LIBWEBRTC_BINARY_PATH)
    message(FATAL_ERROR "LIBWEBRTC_BINARY_PATH is not set.")
endif()

add_library(webrtc STATIC IMPORTED GLOBAL)
set_target_properties(webrtc PROPERTIES
    IMPORTED_LOCATION "${LIBWEBRTC_BINARY_PATH}"
)

# --- libmediasoupclient ---

# 路径需要在调用 CMake 时通过命令行参数传入
set(LIBMEDIASOUPCLIENT_INCLUDE_PATH 
	""
	CACHE
	PATH 
	"Path to mediasoupclient include directory")
set(LIBMEDIASOUPCLIENT_BINARY_PATH 
	""
	CACHE
	FILEPATH 
	"Path to mediasoupclient library file")

# 检查路径是否已设置，如果未设置则配置失败
if(NOT LIBMEDIASOUPCLIENT_INCLUDE_PATH)
    message(FATAL_ERROR "LIBMEDIASOUPCLIENT_INCLUDE_PATH is not set.")
endif()
if(NOT LIBMEDIASOUPCLIENT_BINARY_PATH)
    message(FATAL_ERROR "LIBMEDIASOUPCLIENT_BINARY_PATH is not set.")
endif()

add_library(mediasoupclient STATIC IMPORTED GLOBAL)
set_target_properties(mediasoupclient PROPERTIES
	IMPORTED_LOCATION "${LIBMEDIASOUPCLIENT_BINARY_PATH}"
)

# 声明 mediasoupclient 对 webrtc 的依赖关系
target_link_libraries(mediasoupclient INTERFACE webrtc)

# --- libp2pms_client_sdk ---

# 设置源文件和头文件
set(LIB_SOURCES
	# 源文件（.cpp）
	common/log/spdlog_wrapper.cpp
	common/log/p2pms_log.cpp
	src/p2pms_client.cpp
	src/websocket_client.cpp
	src/ws_msg_dispatcher.cpp
	src/p2pms_util.cpp
	src/p2pms_client_impl.cpp
	src/p2p_call_agent.cpp
	src/sfu_call_agent.cpp
	src/p2sp_call_agent.cpp
	src/capturer_track_source.cpp
	src/capturer_video_source.cpp
	src/video_capturer.cpp
	src/d3d_video_renderer.cpp
	src/video_renderer_manager.cpp
	src/device_manager.cpp
	src/base_call_agent.cpp
	src/sfu_client.cpp
	src/peer_connection_wrapper.cpp

	# 头文件（.hpp）
	common/log/spdlog_wrapper.hpp
	common/log/p2pms_log.hpp
	include/api/p2pms_common.hpp
	include/api/p2pms_client_interface.hpp
	include/p2pms_client.hpp
	include/p2pms_client_impl.hpp
	include/websocket_client.hpp
	include/task_queue.hpp
	include/ws_msg_dispatcher.hpp
	include/message.hpp
	include/p2pms_util.hpp
	include/call_agent_interface.hpp
	include/p2p_call_agent.hpp
	include/sfu_call_agent.hpp
	include/p2sp_call_agent.hpp
	include/capturer_track_source.hpp
	include/capturer_video_source.hpp
	include/video_capturer.hpp
	include/video_renderer_interface.hpp
	include/video_renderer_manager.hpp
	include/d3d_video_renderer.hpp
	include/device_manager.hpp
	include/base_call_agent.hpp
	include/sfu_client.hpp
	include/coro_runner.hpp
	include/peer_connection_wrapper.hpp
	include/track_proxy.hpp
)

# 创建静态库
add_library(${PROJECT_NAME} STATIC ${LIB_SOURCES})

target_compile_definitions(${PROJECT_NAME}
    PUBLIC
		_WEBSOCKETPP_CPP11_RANDOM_DEVICE_
		_WEBSOCKETPP_CPP11_TYPE_TRAITS_
		ASIO_STANDALONE
)

# 步骤 3: 链接 p2pms 到它的依赖项
# 这一行会自动处理 p2pms 对 mediasoupclient 和 webrtc 的头文件包含和链接。
target_link_libraries(${PROJECT_NAME} PUBLIC mediasoupclient webrtc)

if(WIN32)
    # Windows 平台
    # NOMINMAX 是为了防止 windows.h 中的 min/max 宏与 C++ 标准库冲突
    target_compile_definitions(${PROJECT_NAME} PRIVATE WEBRTC_WIN NOMINMAX)
	target_link_libraries(${PROJECT_NAME} PUBLIC d3d11 dxgi)
elseif(APPLE)
    # macOS 或 iOS 平台
    target_compile_definitions(${PROJECT_NAME} PRIVATE WEBRTC_MAC WEBRTC_POSIX)
elseif(UNIX)
    # Linux 或其他类 Unix 平台
    target_compile_definitions(${PROJECT_NAME} PRIVATE WEBRTC_LINUX WEBRTC_POSIX)
endif()

# 设置头文件包含目录
target_include_directories(${PROJECT_NAME} PUBLIC
	$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
	$<INSTALL_INTERFACE:include>
	common/log
	third-party
	third-party/asio-1.30.2/include
	third-party/nlohmann
	${LIBWEBRTC_INCLUDE_PATH}
    ${LIBWEBRTC_INCLUDE_PATH}/third_party/abseil-cpp
    ${LIBWEBRTC_INCLUDE_PATH}/third_party/libyuv/include
	${LIBMEDIASOUPCLIENT_INCLUDE_PATH}
)

# 根据编译器和构建类型设置编译选项
if(MSVC)
	# Windows (MSVC) 编译器选项
	target_compile_options(${PROJECT_NAME} PRIVATE /W4) # /W4 类似于 -Wall -Wextra
	if(CMAKE_BUILD_TYPE STREQUAL "Debug")
		target_compile_options(${PROJECT_NAME} PRIVATE /Zi) # /Zi 用于生成调试信息
	else()
		target_compile_options(${PROJECT_NAME} PRIVATE /O2) # /O2 是发布版优化
	endif()
else()
	# Linux/macOS (GCC/Clang) 编译器选项
	if(CMAKE_BUILD_TYPE STREQUAL "Debug")
		target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -pedantic -g)
	elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
		target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -pedantic -O3)
	endif()
endif()

# 安装库文件
install(TARGETS ${PROJECT_NAME}
	ARCHIVE DESTINATION lib
	LIBRARY DESTINATION lib
	RUNTIME DESTINATION bin
)

# 安装头文件
install(DIRECTORY ${CMAKE_SOURCE_DIR}/include/
	DESTINATION include
	FILES_MATCHING PATTERN ".hpp" PATTERN ".h"
)